using System;
using System.Collections.Generic;
using System.Threading;
using Rhizome.Contract;

namespace Rhizome.Model
{
    public partial class ActiveObjectHost
    {
        #region Nested type: Timer

        private class Timer
        {
            private readonly List<IActiveObject> _list;

            public Timer()
            {
                _list = new List<IActiveObject>();
            }

            public int SleepTime
            {
                get
                {
                    lock (this)
                    {
                        var h = _list.Count - 1;
                        if (h >= 0)
                        {
                            var obj = _list[h];
                            var sleepTime = obj.Timeout - Environment.TickCount;
                            return sleepTime <= 0 ? 1 : sleepTime;
                        }
                    }

                    return Timeout.Infinite;
                }
            }

            public void Remove(IActiveObject item)
            {
                lock (this)
                {
                    item.Sleeping = false;
                    _list.Remove(item);
                }
            }

            public void Add(IActiveObject obj)
            {
                lock (this)
                {
                    var l = 0;
                    var h = _list.Count - 1;
                    while (l <= h)
                    {
                        var i = (l + h)/2;
                        var t = _list[i].Timeout;
                        if (t > obj.Timeout)
                            l = i + 1;
                        else if (t < obj.Timeout)
                            h = i - 1;
                        else
                        {
                            l = i;
                            break;
                        }
                    }
                    _list.Insert(l, obj);
                }
            }

            public void Clear()
            {
                lock (this) _list.Clear();
            }

            public IActiveObject GetReady()
            {
                lock (this)
                {
                    var h = _list.Count - 1;
                    if (h >= 0)
                    {
                        var obj = _list[h];
                        if (Environment.TickCount >= obj.Timeout)
                        {
                            _list.RemoveAt(h);
                            return obj;
                        }
                    }
                }
                return null;
            }
        }

        #endregion
    }
}